package com.auto.video.tv.serial;

import com.auto.video.tv.util.ByteUtil;

import android.content.Context;
import android.content.SharedPreferences;
import android.os.Handler;
import android.serialport.SerialPort;
import android.serialport.SerialPortFinder;
import android.text.TextUtils;
import android.util.Log;

import com.auto.video.tv.AutoVideoApplication;

import org.greenrobot.eventbus.EventBus;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.security.InvalidParameterException;

public class SerialPortControl {
    private static final String TAG = "SerialPortControl";
    private String rootPath = "/dev/ttyS3";
    private int baudrate = 19200;
//    public boolean serialPortStatus = false; //是否打开串口标志
//    private boolean heartBeatStatus = false; //是否正在执行心跳包检测
    public String data_;
    public int serialNumber = 0;
    public boolean isStoped; //线程状态，为了安全终止线程
    //private SerialPortEntity serialPortEntity;
    private Handler handler = new Handler();
    public SerialPort serialPort = null;
    public InputStream inputStream = null;
    public OutputStream outputStream = null;

    public SerialPortFinder mSerialPortFinder = new SerialPortFinder();
    private SerialPort mSerialPort = null;

    public SerialPort getSerialPort(String serialPath) throws SecurityException, IOException, InvalidParameterException {
        if (mSerialPort == null) {
            String packageName = AutoVideoApplication.getApplication().getPackageName();

            /* Check parameters */
            if (TextUtils.isEmpty(serialPath) || (baudrate == -1)) {
                throw new InvalidParameterException();
            }

            /* Open the serial port */
            //mSerialPort = new SerialPort(new File(path), baudrate, 0);

            mSerialPort = SerialPort //
                    .newBuilder(serialPath, baudrate) // 串口地址地址，波特率
                    .parity(2) // 校验位；0:无校验位(NONE，默认)；1:奇校验位(ODD);2:偶校验位(EVEN)
                    .dataBits(7) // 数据位,默认8；可选值为5~8
                    .stopBits(2) // 停止位，默认1；1:1位停止位；2:2位停止位
                    .build();
        }
        return mSerialPort;
    }

    public void closeSerialPort() {
        if (mSerialPort != null) {
            mSerialPort.close();
            mSerialPort = null;
        }
    }

    /**
     * 发送串口指令
     */
    public void sendSerialPort(byte[] sendData) {
        Log.d(TAG, "sendSerialPort: 发送数据");
        try {
            if (sendData.length > 0) {
                outputStream.write(sendData);
                outputStream.write('\n');
                //outputStream.write('\r'+'\n');
                outputStream.flush();
                Log.d(TAG, "sendSerialPort: 串口数据发送成功 " + this.data_);
            }
        } catch (IOException e) {
            Log.e(TAG, "sendSerialPort: 串口数据发送失败：" + e.toString());
        }
    }

    /**
     * 单开一线程，来读数据
     */
    private class ReadThread extends Thread {
        @Override
        public void run() {
            super.run();
            Log.d(TAG, "openSerialPort: 打开串口");
            //判断进程是否在运行，更安全的结束进程
            while (!isStoped) {
                Log.d(TAG, "进入读数据线程run");
                //64   1024
                byte[] buffer = new byte[1024];
                int size; //读取数据的大小
                try {
                    size = inputStream.read(buffer);
                    if (size > 0) {
                        Log.d(TAG, "run: 接收到了数据：" + ByteUtil.toHexString(buffer));
                        Log.d(TAG, "run: 接收到了数据大小：" + String.valueOf(size));
//                        String readString = byteArrToHex(readData, 0, size);
                        EventBus.getDefault().post(ByteUtil.toHexString(buffer));
                    }
                } catch (IOException e) {
                    Log.e(TAG, "run: 数据读取异常：" + e.toString());
                }
            }

        }
    }

    /**
     * 心跳检测
     */
    public void openHeartBeatCheck() {
        if (!isStoped) {
            handler.postDelayed(heartBeatRunnable, 10000);
        }
    }

    Runnable heartBeatRunnable = new Runnable() {
        @Override
        public void run() {
            while (!isStoped) {
                Log.d(TAG, "进入心跳线程run");
                String timeString = ByteUtil.hexTimeString();
                sendCommand(FlagManager.SEND_HEARTBEAT, "02" + timeString);
//                byte[] sendData = new byte[]{0x11, (byte) 0xAA, 0x01, 0x01, 0x02, 0x04, 0x55};
            }
        }
    };

    /**
     * 上位机下发命令
     *
     * @param code
     * @param data String数据
     */
    public void sendCommand(int code, String data) {
        String head = "11AA";
        int data_length = data.length() / 2;
        int num = this.serialNumber;
        this.serialNumber++;
        if (this.serialNumber > 255) {
            this.serialNumber = 0;
        }
        String code_hexstring = ByteUtil.byteToHex(code);
        String serialNumber_hexstring = ByteUtil.byteToHex(serialNumber);
        String data_length_hexstring = ByteUtil.byteToHex(data_length);
        String precheck = code_hexstring + serialNumber_hexstring + data_length_hexstring + data;
        byte[] precheck_array = ByteUtil.toByteArray(precheck);
        int check = ByteUtil.checkDigit(precheck_array);
        String hex_code = head + precheck + ByteUtil.byteToHex(check) + "55";
        byte[] byte_hex_code = ByteUtil.toByteArray(hex_code);
        this.sendSerialPort(byte_hex_code);   
    }

    /**
     * 上位机下发设置信息
     */
    public void sendSetInfo(float temperature, float humidity, float ammonia, float hydrogen_sulfide, float illumination) {
        String s_temperature = ByteUtil.floatToHexString(temperature,100);
        String s_humidity = ByteUtil.floatToHexString(humidity,100);
        String s_ammonia = ByteUtil.floatToHexString(ammonia,1000);
        String s_hydrogen_sulfide = ByteUtil.floatToHexString(hydrogen_sulfide,1000);
        String s_illumination = ByteUtil.floatToHexString(illumination,1);
        String data = s_temperature + s_humidity + s_ammonia + s_hydrogen_sulfide + s_illumination;
        sendCommand(FlagManager.SEND_SETTINGS, data);
    }

    /**
     * 上位机下发升级标记
     */
    public void sendUpdateInfo() {
        sendCommand(FlagManager.SEND_UPGRADE_COMMAND, "0310");
    }

    /**
     * 上位机下发升级数据包
     */
    public void sendUpdateData() {
        sendCommand(FlagManager.SEND_UPGRADE_DATA, "0410");
    }
}
